//////////////////////////////////////////////////////////////////////
////                                                              ////
////  can_bsp.v                                                   ////
////                                                              ////
////                                                              ////
////  This file is part of the CAN Protocol Controller            ////
////  http://www.opencores.org/projects/can/                      ////
////                                                              ////
////                                                              ////
////  Author(s):                                                  ////
////       Igor Mohor                                             ////
////       igorm@opencores.org                                    ////
////                                                              ////
////                                                              ////
////  All additional information is available in the README.txt   ////
////  file.                                                       ////
////                                                              ////
//////////////////////////////////////////////////////////////////////
////                                                              ////
//// Copyright (C) 2002, 2003, 2004 Authors                       ////
////                                                              ////
//// This source file may be used and distributed without         ////
//// restriction provided that this copyright statement is not    ////
//// removed from the file and that any derivative work contains  ////
//// the original copyright notice and the associated disclaimer. ////
////                                                              ////
//// This source file is free software; you can redistribute it   ////
//// and/or modify it under the terms of the GNU Lesser General   ////
//// Public License as published by the Free Software Foundation; ////
//// either version 2.1 of the License, or (at your option) any   ////
//// later version.                                               ////
////                                                              ////
//// This source is distributed in the hope that it will be       ////
//// useful, but WITHOUT ANY WARRANTY; without even the implied   ////
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      ////
//// PURPOSE.  See the GNU Lesser General Public License for more ////
//// details.                                                     ////
////                                                              ////
//// You should have received a copy of the GNU Lesser General    ////
//// Public License along with this source; if not, download it   ////
//// from http://www.opencores.org/lgpl.shtml                     ////
////                                                              ////
//// The CAN protocol is developed by Robert Bosch GmbH and       ////
//// protected by patents. Anybody who wants to implement this    ////
//// CAN IP core on silicon has to obtain a CAN protocol license  ////
//// from Bosch.                                                  ////
////                                                              ////
//////////////////////////////////////////////////////////////////////
//
// CVS Revision History
//
// $Log: not supported by cvs2svn $
// Revision 1.52  2004/11/18 12:39:21  igorm
// Fixes for compatibility after the SW reset.
//
// Revision 1.51  2004/11/15 18:23:21  igorm
// When CAN was reset by setting the reset_mode signal in mode register, it
// was possible that CAN was blocked for a short period of time. Problem
// occured very rarly.
//
// Revision 1.50  2004/10/27 18:51:36  igorm
// Fixed synchronization problem in real hardware when 0xf is used for TSEG1.
//
// Revision 1.49  2004/10/25 06:37:51  igorm
// Arbitration bug fixed.
//
// Revision 1.48  2004/05/12 15:58:41  igorm
// Core improved to pass all tests with the Bosch VHDL Reference system.
//
// Revision 1.47  2004/02/08 14:24:10  mohor
// Error counters changed.
//
// Revision 1.46  2003/10/17 05:55:20  markom
// mbist signals updated according to newest convention
//
// Revision 1.45  2003/09/30 21:14:33  mohor
// Error counters changed.
//
// Revision 1.44  2003/09/30 00:55:12  mohor
// Error counters fixed to be compatible with Bosch VHDL reference model.
// Small synchronization changes.
//
// Revision 1.43  2003/09/25 18:55:49  mohor
// Synchronization changed, error counters fixed.
//
// Revision 1.42  2003/08/29 07:01:14  mohor
// When detecting bus-free, signal bus_free_cnt_en was cleared to zero
// although the last sampled bit was zero instead of one.
//
// Revision 1.41  2003/07/18 15:23:31  tadejm
// Tx and rx length are limited to 8 bytes regardless to the DLC value.
//
// Revision 1.40  2003/07/16 15:10:17  mohor
// Fixed according to the linter.
//
// Revision 1.39  2003/07/16 13:12:46  mohor
// Fixed according to the linter.
//
// Revision 1.38  2003/07/10 01:59:04  tadejm
// Synchronization fixed. In some strange cases it didn't work according to
// the VHDL reference model.
//
// Revision 1.37  2003/07/07 11:21:37  mohor
// Little fixes (to fix warnings).
//
// Revision 1.36  2003/07/03 09:32:20  mohor
// Synchronization changed.
//
// Revision 1.35  2003/06/27 20:56:12  simons
// Virtual silicon ram instances added.
//
// Revision 1.34  2003/06/22 09:43:03  mohor
// synthesi full_case parallel_case fixed.
//
// Revision 1.33  2003/06/21 12:16:30  mohor
// paralel_case and full_case compiler directives added to case statements.
//
// Revision 1.32  2003/06/17 14:28:32  mohor
// Form error was detected when stuff bit occured at the end of crc.
//
// Revision 1.31  2003/06/16 14:31:29  tadejm
// Bit stuffing corrected when stuffing comes at the end of the crc.
//
// Revision 1.30  2003/06/16 13:57:58  mohor
// tx_point generated one clk earlier. rx_i registered. Data corrected when
// using extended mode.
//
// Revision 1.29  2003/06/11 14:21:35  mohor
// When switching to tx, sync stage is overjumped.
//
// Revision 1.28  2003/03/01 22:53:33  mohor
// Actel APA ram supported.
//
// Revision 1.27  2003/02/20 00:26:02  mohor
// When a dominant bit was detected at the third bit of the intermission and
// node had a message to transmit, bit_stuff error could occur. Fixed.
//
// Revision 1.26  2003/02/19 23:21:54  mohor
// When bit error occured while active error flag was transmitted, counter was
// not incremented.
//
// Revision 1.25  2003/02/19 14:44:03  mohor
// CAN core finished. Host interface added. Registers finished.
// Synchronization to the wishbone finished.
//
// Revision 1.24  2003/02/18 00:10:15  mohor
// Most of the registers added. Registers "arbitration lost capture", "error code
// capture" + few more still need to be added.
//
// Revision 1.23  2003/02/14 20:17:01  mohor
// Several registers added. Not finished, yet.
//
// Revision 1.22  2003/02/12 14:23:59  mohor
// abort_tx added. Bit destuff fixed.
//
// Revision 1.21  2003/02/11 00:56:06  mohor
// Wishbone interface added.
//
// Revision 1.20  2003/02/10 16:02:11  mohor
// CAN is working according to the specification. WB interface and more
// registers (status, IRQ, ...) needs to be added.
//
// Revision 1.19  2003/02/09 18:40:29  mohor
// Overload fixed. Hard synchronization also enabled at the last bit of
// interframe.
//
// Revision 1.18  2003/02/09 02:24:33  mohor
// Bosch license warning added. Error counters finished. Overload frames
// still need to be fixed.
//
// Revision 1.17  2003/02/04 17:24:41  mohor
// Backup.
//
// Revision 1.16  2003/02/04 14:34:52  mohor
// *** empty log message ***
//
// Revision 1.15  2003/01/31 01:13:37  mohor
// backup.
//
// Revision 1.14  2003/01/16 13:36:19  mohor
// Form error supported. When receiving messages, last bit of the end-of-frame
// does not generate form error. Receiver goes to the idle mode one bit sooner.
// (CAN specification ver 2.0, part B, page 57).
//
// Revision 1.13  2003/01/15 21:59:45  mohor
// Data is stored to fifo at the end of ack stage.
//
// Revision 1.12  2003/01/15 21:05:11  mohor
// CRC checking fixed (when bitstuff occurs at the end of a CRC sequence).
//
// Revision 1.11  2003/01/15 14:40:23  mohor
// RX state machine fixed to receive "remote request" frames correctly.
// No data bytes are written to fifo when such frames are received.
//
// Revision 1.10  2003/01/15 13:16:47  mohor
// When a frame with "remote request" is received, no data is stored to
// fifo, just the frame information (identifier, ...). Data length that
// is stored is the received data length and not the actual data length
// that is stored to fifo.
//
// Revision 1.9  2003/01/14 12:19:35  mohor
// rx_fifo is now working.
//
// Revision 1.8  2003/01/10 17:51:33  mohor
// Temporary version (backup).
//
// Revision 1.7  2003/01/09 21:54:45  mohor
// rx fifo added. Not 100 % verified, yet.
//
// Revision 1.6  2003/01/09 14:46:58  mohor
// Temporary files (backup).
//
// Revision 1.5  2003/01/08 13:30:31  mohor
// Temp version.
//
// Revision 1.4  2003/01/08 02:10:53  mohor
// Acceptance filter added.
//
// Revision 1.3  2002/12/28 04:13:23  mohor
// Backup version.
//
// Revision 1.2  2002/12/27 00:12:52  mohor
// Header changed, testbench improved to send a frame (crc still missing).
//
// Revision 1.1.1.1  2002/12/20 16:39:21  mohor
// Initial
//
//
//

// synopsys translate_off

// synopsys translate_on




module can_fd_filter #(
    parameter integer NSAMPLES = 3
) (
  input wire  rst,
  input wire  clk,
  input wire  rx_sync_i,
  output reg  filteredrx_ro,
  output wire fall_edge_o
);

localparam integer SHIFT_REG_LEN = NSAMPLES-1;

reg   [SHIFT_REG_LEN-1:0]  shift_r;
wire allzero;
wire allone;

/*
    Report edge detection 1 cycle early, so that unnecessary delay
    is avoided (can_fd_detect already has the correct 1 cycle delay).
*/
assign fall_edge_o = allzero & filteredrx_ro;

always @ (posedge clk or posedge rst)
begin
  if (rst)
    shift_r <= {(SHIFT_REG_LEN){1'b1}};
  else
    shift_r <= {shift_r[SHIFT_REG_LEN-2 : 0], rx_sync_i};
end

assign allzero = ((| shift_r) | rx_sync_i) == 1'b0;
assign allone =  ((& shift_r) & rx_sync_i) == 1'b1;

always @ (posedge clk or posedge rst)
begin
  if (rst)
    filteredrx_ro <= 1'b1;
  else if (allone)
    filteredrx_ro <= 1'b1;
  else if (allzero)
    filteredrx_ro <= 1'b0;
end

endmodule
//------------------------------------------------------------------------------

module can_fd_detect (
  input wire  rst,
  input wire  clk,

  input wire  sample_point_i,
  input wire  fall_edge_i,     // from can_fd_filter

  // Fall-edge in last bit time;
  // Set on 1-to-0 transition in FD mode (on fast clock), reset on sample_point
  output reg  fall_edge_lstbtm_ro
);

always @ (posedge clk or posedge rst)
begin
  if (rst)
    fall_edge_lstbtm_ro <= 1'b0;
  else if (sample_point_i)
    /* Reset on sample_point has precedence. The register is read in the same cycle,
       *and* the RX signal itself is read in that cycle, so the dominant state
       is accounted for anyway.
    */
    fall_edge_lstbtm_ro <= 1'b0;
  else if (fall_edge_i)
    fall_edge_lstbtm_ro <= 1'b1;
end

endmodule

//------------------------------------------------------------------------------

module can_bsp
(
  input  wire        clk,
  input  wire        rst,

  input  wire        sample_point,
  input  wire        sampled_bit,
  input  wire        sampled_bit_q,
  input  wire        tx_point,
  input  wire        hard_sync,

  input  wire  [7:0] addr, // FIFO read address only
  input  wire  [31:0] data_in, // input data for FIFO and error count settings (looks magical :/)
  output wire  [31:0] data_out, // from FIFO only
  input  wire        fifo_selected, // only forwarded

  input  wire        rx_sync_i, // raw RX for busy detection on fast data rate
  output wire        go_rx_skip_fdf_o,
  output wire        fdf_o,

  output wire        fdf_brs_on_o,
  output wire        go_rx_brs_on_o,


  /* Mode register */
  input  wire        reset_mode,
  input  wire        listen_only_mode,
  input  wire        acceptance_filter_mode,
  input  wire        self_test_mode,

  /* Command register */
  input  wire        release_buffer,
  input  wire        tx_request,
  input  wire        abort_tx,
  input  wire        self_rx_request,
  input  wire        single_shot_transmission,
  output reg         tx_state,
  output reg         tx_state_q,
  input  wire        overload_request,     // When receiver is busy, it needs to send overload frame. Only 2 overload frames are allowed to
  output wire         overload_frame,       // be send in a row. This is not implemented, yet,  because host can not send an overload request.

  /* Arbitration Lost Capture Register */
  input  wire        read_arbitration_lost_capture_reg,

  /* Error Code Capture Register */
  input  wire        read_error_code_capture_reg,
  output reg   [7:0] error_capture_code,

  /* Error Warning Limit register */
  input  wire  [7:0] error_warning_limit,

  /* FD Control Register  */
  input wire en_FD_rx, /* Quando for 0, o controlador deverá operar como FD Tolerant */
  input wire en_FD_iso, /* Altera entre FD ISO (1) e FD non-ISO (0) */

  /* Rx Error Counter register */
  input  wire        we_rx_err_cnt,

  /* Tx Error Counter register */
  input  wire        we_tx_err_cnt,

  /* Clock Divider register */
  input  wire        extended_mode,

  output wire        fdf_detected,
  output reg         rx_r0_fd,
  output wire        rx_idle,
  output wire        transmitting,
  output reg         transmitter,
  output wire        go_rx_inter,
  output wire        not_first_bit_of_inter,
  output wire        rx_inter,
  output wire        set_reset_mode,
  output reg         node_bus_off,
  output wire        error_status,
  output reg   [8:0] rx_err_cnt,
  output reg   [8:0] tx_err_cnt,
  output wire        transmit_status,
  output wire        receive_status,
  output wire        tx_successful,
  output reg         need_to_tx,        // When the CAN core has something to transmit and a dominant bit is sampled at the third bit
  output wire        overrun,
  output wire        info_empty,
  output wire        set_bus_error_irq,
  output wire        set_arbitration_lost_irq,
  output reg   [4:0] arbitration_lost_capture,
  output reg         node_error_passive,
  output wire        node_error_active,
  output wire  [6:0] rx_message_counter,

  /* This section is for BASIC and EXTENDED mode */
  /* Acceptance code register */
  input  wire  [7:0] acceptance_code_0,

  /* Acceptance mask register */
  input  wire  [7:0] acceptance_mask_0,
  /* End: This section is for BASIC and EXTENDED mode */

  /* This section is for EXTENDED mode */
  /* Acceptance code register */
  input  wire  [7:0] acceptance_code_1,
  input  wire  [7:0] acceptance_code_2,
  input  wire  [7:0] acceptance_code_3,

  /* Acceptance mask register */
  input  wire  [7:0] acceptance_mask_1,
  input  wire  [7:0] acceptance_mask_2,
  input  wire  [7:0] acceptance_mask_3,
  /* End: This section is for EXTENDED mode */

  /* Tx data registers. Holding identifier (basic mode), tx frame information (extended mode) and data */
  input  wire  [7:0] tx_data_0,
  input  wire  [7:0] tx_data_1,
  input  wire  [7:0] tx_data_2,
  input  wire  [7:0] tx_data_3,
  input  wire  [7:0] tx_data_4,
  input  wire  [7:0] tx_data_5,
  input  wire  [7:0] tx_data_6,
  input  wire  [7:0] tx_data_7,
  input  wire  [7:0] tx_data_8,
  input  wire  [7:0] tx_data_9,
  input  wire  [7:0] tx_data_10,
  input  wire  [7:0] tx_data_11,
  input  wire  [7:0] tx_data_12,
  /* End: Tx data registers */

  /* Tx signal */
  output reg         tx,
  output reg         tx_next,
  output wire        bus_off_on,

  output wire        go_overload_frame,
  output wire        go_error_frame,
  output wire        go_tx,
  output wire        send_ack
);

reg           reset_mode_q;
reg     [8:0] bit_cnt; // FD Frames ( 512 bits  contagem maxima para o campo de DATA)

wire    [6:0] data_len;
reg     [3:0] data_len_code;

reg    [28:0] id;
reg     [2:0] bit_stuff_cnt;
reg     [2:0] bit_stuff_cnt_tx;
reg           tx_point_q;

reg     [3:0] stuff_cnt;

wire           rx_id1;
wire           rx_rtr1;
wire           rx_ide;
wire           rx_id2;
wire           rx_rtr2;
wire           rx_r1;
wire           rx_r0;
wire           rx_brs;
wire           rx_esi;
wire           rx_dlc;
wire           rx_data;
wire           rx_stuff_count;
wire           rx_crc;
wire           rx_crc_lim;
wire           rx_ack;
wire           rx_ack_fd_1;
wire           rx_ack_fd_2; // Extra ACK Slot segment for handling phase shift on FD frames
wire           rx_ack_lim;
wire           rx_eof;
reg           go_early_tx_latched;

reg           rtr1;
reg           ide;
reg           brs;
reg           esi;
reg           edl; 
reg           rtr2;
reg    [14:0] crc_in_15;
reg    [16:0] crc_in_17;
reg    [20:0] crc_in_21;


reg           bit_stuff_cnt_en;
reg           crc_enable;

reg     [2:0] eof_cnt;
reg     [2:0] passive_cnt;

wire          error_frame;
reg           enable_error_cnt2;
reg     [2:0] error_cnt1;
reg     [2:0] error_cnt2;
reg     [2:0] delayed_dominant_cnt;
reg           enable_overload_cnt2;
reg           overload_frame_blocked;
reg     [1:0] overload_request_cnt;
reg     [2:0] overload_cnt1;
reg     [2:0] overload_cnt2;
reg           crc_err;

reg           arbitration_lost;
reg           arbitration_lost_q;
reg           arbitration_field_d;
reg     [4:0] arbitration_cnt;
reg           arbitration_blocked;
reg           tx_q;

reg     [6:0] data_cnt;     // Counting the data bytes that are written to FIFO
reg     [2:0] header_cnt;   // Counting header length
reg           wr_fifo;      // Write data and header to 64-byte fifo
reg     [31:0] data_for_fifo;// Multiplexed data that is stored to 64-byte fifo

reg     [5:0] tx_pointer;
reg           tx_bit;
reg           finish_msg;

reg     [3:0] bus_free_cnt;
reg           bus_free_cnt_en;
reg           bus_free;
wire          bus_free_uncond;
reg           waiting_for_bus_free;

reg           node_bus_off_q;
reg           ack_err_latched;
reg           bit_err_latched;
reg           stuff_err_latched;
reg           form_err_latched;
reg           rule3_exc1_1;
reg           rule3_exc1_2;
reg           suspend;
reg           susp_cnt_en;
reg     [2:0] susp_cnt;
reg           error_flag_over_latched;

reg     [7:6] error_capture_code_type;
reg           error_capture_code_blocked;
reg           first_compare_bit;

/* Actual received frame is CAN FD one and needs to be ignored */
wire          rx_skip_fdf;

// Permanece dominante enquanto o frame FD estiver sendo transmitido com a Data Bit Rate
reg           fdf_brs_r;

/* Fall edge detected inside preceding bittime */
wire          fd_fall_edge_lstbtm;

wire          fd_fall_edge_raw;

reg           go_rx_skip_fdf; // async
reg     [3:0] fd_skip_cnt;
wire          fd_skip_finished;


wire    [4:0] error_capture_code_segment;
wire          error_capture_code_direction;

reg           bit_de_stuff;
wire          bit_de_stuff_tx;

wire          rule5;

// Operation Control State Machine
wire          go_oc_transmitting;
wire          go_oc_receiving;
wire          go_oc_idle;
wire          go_oc_integrating;

/* Rx state machine */
wire          go_rx_integrating;
wire          go_rx_idle;
wire          go_rx_id1;
wire          go_rx_rtr1;
wire          go_rx_ide;
wire          go_rx_id2;
wire          go_rx_rtr2;
wire          go_rx_r1;
wire          go_rx_r0;
wire          go_rx_r0_fd; 
wire          go_rx_brs; 
wire          go_rx_esi;
wire          go_rx_dlc;
wire          go_rx_data;
wire          go_rx_stuff_count;
wire          go_rx_crc;
wire          go_rx_crc_lim;
wire          go_rx_ack;
wire          go_rx_ack_fd_1;
wire          go_rx_ack_fd_2;
wire          go_rx_ack_lim;
wire          go_rx_eof;
//wire          go_rx_inter;

wire          last_bit_of_inter;

wire          go_crc_enable;
wire          rst_crc_enable;

wire          bit_de_stuff_set;
wire          bit_de_stuff_reset;

wire          go_early_tx;

wire   [14:0] calculated_crc_tx;
wire   [14:0] calculated_crc_15;
wire   [16:0] calculated_crc_17;
wire   [20:0] calculated_crc_21;
wire   [15:0] r_calculated_crc;
wire          remote_rq;

wire          form_err;

wire          error_frame_ended;
wire          overload_frame_ended;
wire          bit_err;
wire          ack_err;
wire          stuff_err;
wire          fixed_stuff_bit_error;

wire          id_ok;                // If received ID matches ID set in registers
wire          no_byte0;             // There is no byte 0 (RTR bit set to 1 or DLC field equal to 0). Signal used for acceptance filter.
wire          no_byte1;             // There is no byte 1 (RTR bit set to 1 or DLC field equal to 1). Signal used for acceptance filter.

wire    [2:0] header_len;
wire          storing_header;
wire    [6:0] limited_data_len_minus1;
wire          reset_wr_fifo;
wire          err;

wire          arbitration_field;

wire   [18:0] basic_chain;
wire   [63:0] basic_chain_data;
wire   [18:0] extended_chain_std;
wire   [38:0] extended_chain_ext;
wire   [63:0] extended_chain_data_std;
wire   [63:0] extended_chain_data_ext;

wire          rst_tx_pointer;

wire    [7:0] r_tx_data_0;
wire    [7:0] r_tx_data_1;
wire    [7:0] r_tx_data_2;
wire    [7:0] r_tx_data_3;
wire    [7:0] r_tx_data_4;
wire    [7:0] r_tx_data_5;
wire    [7:0] r_tx_data_6;
wire    [7:0] r_tx_data_7;
wire    [7:0] r_tx_data_8;
wire    [7:0] r_tx_data_9;
wire    [7:0] r_tx_data_10;
wire    [7:0] r_tx_data_11;
wire    [7:0] r_tx_data_12;

wire          bit_err_exc1;
wire          bit_err_exc2;
wire          bit_err_exc3;
wire          bit_err_exc4;
wire          bit_err_exc5;
wire          bit_err_exc6;
wire          error_flag_over;
wire          overload_flag_over;
wire          enable_crc_destuff;

wire go_rx_inter_acf;
wire go_error_frame_acf;

wire    [5:0] limited_tx_cnt_ext;
wire    [5:0] limited_tx_cnt_std;

assign FD_tolerant    = (~en_FD_rx);

assign rst_crc_enable = FD_tolerant ? (go_rx_crc | go_rx_skip_fdf) : (go_rx_crc);

assign bit_de_stuff_set   = go_rx_id1 & (~go_error_frame);

assign bit_de_stuff_reset = FD_tolerant ? (go_rx_ack | go_error_frame | go_overload_frame | go_rx_skip_fdf) : (go_rx_ack | go_rx_ack_fd_1 | go_rx_ack_fd_2 | go_error_frame | go_overload_frame);

assign remote_rq = ((~ide) & rtr1) | (ide & rtr2);

assign ack_err = rx_ack & sample_point & sampled_bit & tx_state & (~self_test_mode);
assign bit_err = (tx_state | error_frame | overload_frame | rx_ack) & sample_point & (tx != sampled_bit) & (~bit_err_exc1) & (~bit_err_exc2) & (~bit_err_exc3) & (~bit_err_exc4) & (~bit_err_exc5) & (~bit_err_exc6) & (~reset_mode);
assign bit_err_exc1 = tx_state & arbitration_field & tx;
assign bit_err_exc2 = (rx_ack | rx_ack_fd_1 | rx_ack_fd_2) & tx;
assign bit_err_exc3 = error_frame & node_error_passive & (error_cnt1 < 3'd7);
assign bit_err_exc4 = (error_frame & (error_cnt1 == 3'd7) & (~enable_error_cnt2)) | (overload_frame & (overload_cnt1 == 3'd7) & (~enable_overload_cnt2));
assign bit_err_exc5 = (error_frame & (error_cnt2 == 3'd7)) | (overload_frame & (overload_cnt2 == 3'd7));
assign bit_err_exc6 = (eof_cnt == 3'd6) & rx_eof & (~transmitter);

assign arbitration_field = rx_id1 | rx_rtr1 | rx_ide | rx_id2 | rx_rtr2;

assign last_bit_of_inter = rx_inter & (bit_cnt[1:0] == 2'd2);
assign not_first_bit_of_inter = rx_inter & (bit_cnt[1:0] != 2'd0);


assign fdf_brs_on_o = fdf_brs_r;
assign go_rx_brs_on_o = sample_point & rx_brs & (~bit_de_stuff) & sampled_bit;


// FD Detection
assign fdf_detected = (sample_point & sampled_bit & (~bit_de_stuff)) & ( (rx_r0 & (~ide)) | (rx_r1 & ide) );


// Permanece recessivo enquanto o frame FD estiver sendo transmitido com a Data Bit Rate
always @ (posedge clk or posedge rst)
begin
  if (rst)
    fdf_brs_r <= 1'b0;
  else if (reset_mode | go_rx_inter | go_error_frame | go_rx_ack | go_rx_ack_fd_1 )
    fdf_brs_r <= 1'b0;
  else if (go_rx_brs_on_o)
    fdf_brs_r <= 1'b1;
end

// Decodifica o valor do campo DLC
can_dlc_decoder i_can_dlc_decoder(
  .data_len_in(data_len_code),
  .data_len_out(data_len),
  .fd_frame_in(edl)
);
 
assign go_rx_skip_fdf_o = go_rx_skip_fdf;
assign fdf_o = rx_skip_fdf;

/*
    Idea:
    - after every CAN DATA  frame there must be 7 recessive bits for EOF + 1 ACK delimiter (+3 intermission)
    - after every CAN ERROR frame there must be 8 recessive bits as delimiter (+3 intermission)
    - when FD frame is detected, just wait until the X recessive bits are found

    Wait only until first bit of intermission and then go to rx_inter. That way all the funny stuff
    with SOF and resynchronization are handled correctly.
*/
assign fd_skip_finished = fd_skip_cnt >= 4'd8;

can_fd_filter #(
  .NSAMPLES(3)
) i_can_fd_filter (
  .rst(rst),
  .clk(clk),
  .rx_sync_i(rx_sync_i),
  .filteredrx_ro(),
  .fall_edge_o(fd_fall_edge_raw)
);

can_fd_detect i_can_fd_detect (
  .rst(rst),
  .clk(clk),
  /* from can_fd_filter */
  .fall_edge_i(fd_fall_edge_raw),
  .sample_point_i(sample_point),

  .fall_edge_lstbtm_ro(fd_fall_edge_lstbtm)
);

always @(posedge clk or posedge rst)
begin
  if (rst)
    fd_skip_cnt <= 4'h0;
  else if (go_rx_inter | reset_mode)
    fd_skip_cnt <= 4'h0;
  else if (go_rx_skip_fdf | (sample_point & (~sampled_bit | fd_fall_edge_lstbtm)))
    fd_skip_cnt <= 4'h0;
  else if (rx_skip_fdf & sample_point & fd_skip_cnt < 4'd8)
    fd_skip_cnt <= fd_skip_cnt + 1'b1;
end



// ID register
always @ (posedge clk or posedge rst)
begin
  if (rst)
    id <= 29'h0;
  else if (sample_point & (rx_id1 | rx_id2) & (~bit_de_stuff))
    id <= {id[27:0], sampled_bit};
end


// rtr1 bit
always @ (posedge clk or posedge rst)
begin
  if (rst)
    rtr1 <= 1'b0;
  else if (sample_point & rx_rtr1 & (~bit_de_stuff))
    rtr1 <= sampled_bit;
end


// rtr2 bit
always @ (posedge clk or posedge rst)
begin
  if (rst)
    rtr2 <= 1'b0;
  else if (sample_point & rx_rtr2 & (~bit_de_stuff))
    rtr2 <= sampled_bit;
end


// ide bit
always @ (posedge clk or posedge rst)
begin
  if (rst)
    ide <= 1'b0;
  else if (sample_point & rx_ide & (~bit_de_stuff))
    ide <= sampled_bit;
end

// edl bit (Apenas em frames FD)
always @ (posedge clk or posedge rst)
begin
  if (rst)
    edl <= 1'b0;
  else if(rx_r0 & ~sampled_bit)
    edl <= 1'b0; // Em caso de frames nao FD, o valor de edl nao sera gravado e, para isso, deve ser resetado.
  else if (go_rx_r0_fd)
    edl <= 1'b1;
end

// brs bit
always @ (posedge clk or posedge rst)
begin
  if (rst)
    brs <= 1'b0;
  else if(rx_r0)
    brs <= 1'b0; // Em caso de frames nao FD, o valor de brs nao sera gravado e, para isso, deve ser resetado.
  else if (sample_point & rx_brs & (~bit_de_stuff))
    brs <= sampled_bit;
end

// esi bit
always @ (posedge clk or posedge rst)
begin
  if (rst)
    esi <= 1'b0;
  else if(rx_r0)
    esi <= 1'b0; // Em caso de frames nao FD, o valor de esi nao sera gravado e, para isso, deve ser resetado.
  else if (sample_point & rx_esi & (~bit_de_stuff))
    esi <= sampled_bit;
end


// Data length
always @ (posedge clk or posedge rst)
begin
  if (rst)
    data_len_code <= 4'b0;
  else if (sample_point & rx_dlc & (~bit_de_stuff))
    data_len_code <= {data_len_code[2:0], sampled_bit};
end


// CRC Stuff Count
always @ (posedge clk or posedge rst)
begin
  if (rst)
    stuff_cnt <= 4'b0;
  else if (sample_point & rx_stuff_count & (~bit_de_stuff))
    stuff_cnt <= {stuff_cnt[2:0], sampled_bit};
end


// ---------------------- FIFO Wr -------------------------------
logic           data_byte_detected;
logic     [7:0] tmp_byte_data;
logic    [31:0] tmp_fifo [0:15];
logic    [31:0] tmp_4_byte_data;
logic     [5:0] byte_cnt;
logic     [5:0] word_cnt;
logic     [4:0] wr_operations;
logic     [1:0] byte_in_word_cnt;  // Contador de 0 a 3
logic           tmp_fifo_wr_add;

// Amount of FIFO write operations
assign wr_opeations =( data_len >> 2) + 1'b1;


// Store each data byte
always @ (posedge clk or posedge rst)
begin
  if (rst)
    tmp_byte_data <= 8'h0;
  else if (sample_point & rx_data & (~bit_de_stuff))
    tmp_byte_data <= {tmp_byte_data[6:0], sampled_bit};
end

// Store each data 4 byte
always @ (posedge clk or posedge rst)
begin
  if (rst)
    tmp_4_byte_data <= 32'h0;
  else if (sample_point & rx_data & (~bit_de_stuff))
    tmp_4_byte_data <= {tmp_4_byte_data[30:0], sampled_bit};
end

// Detect data byte 
always @ (posedge clk or posedge rst)
begin
  if (rst)
    data_byte_detected <= 1'b0;
  else if (sample_point & rx_data & (~bit_de_stuff) & (&bit_cnt[2:0]))
    data_byte_detected <= 1'b1;
  else
    data_byte_detected <= 1'b0;
end

always @ (posedge clk or posedge rst)
begin
  if (rst)
    byte_cnt <= 6'h0;
  else if (data_byte_detected)
    byte_cnt <= byte_cnt + 1'b1;
  else if (sample_point & go_rx_crc_lim)
    byte_cnt <= 6'h0;
end

always @ (posedge clk)
begin
  if(~extended_mode) begin
    if (data_byte_detected) begin
      tmp_fifo[byte_cnt] <= {24'b0, tmp_byte_data};
    end
  end
  else begin
    if (data_byte_detected) begin
       tmp_fifo[ (byte_cnt >> 2) ] <= tmp_4_byte_data;
    end
  end
end


// CRC

always @ (posedge clk or posedge rst)
begin
  if (rst) begin
    crc_in_15 <= 15'h0;
  end
  else if (sample_point & rx_crc & (~bit_de_stuff)) begin
    crc_in_15 <= {crc_in_15[13:0], sampled_bit};
  end
end

can_crc_destuff can_crc_destuff
(
  .clk(clk),
  .rst(rst),
  .data(sampled_bit),
  .data_prev(sampled_bit_q),
  .enable(sample_point & rx_crc & edl),
  .bit_cnt(bit_cnt),
  .fixed_stuff_bit_error(fixed_stuff_bit_error),
  .en_FD_iso(en_FD_iso),
  .crc_17_o(crc_in_17),
  .crc_21_o(crc_in_21)
);

// Stuff bit must be detected on first bit of rx_stuff_count according to ISO
wire bit_de_stuff_rx_stuff_count;
reg [2:0] bit_cnt_rx_stuff_cnt;

always_ff @(posedge clk, posedge rst) begin
  if(rst)
    bit_cnt_rx_stuff_cnt <= 3'b0;
  else if (sample_point & rx_stuff_count)
    bit_cnt_rx_stuff_cnt <= bit_cnt_rx_stuff_cnt + 1'b1;
  else if(sample_point & (go_rx_crc | go_error_frame))
    bit_cnt_rx_stuff_cnt <= 3'b0;
end


assign bit_de_stuff_rx_stuff_count = rx_stuff_count & ( bit_cnt_rx_stuff_cnt == 3'b0);

// bit_cnt (Conta os bits em cada estado da FSM, utilizado para contar estados que sao compostos de mais de um bit)
always @ (posedge clk or posedge rst)
begin
  if (rst)
    bit_cnt <= 9'd0;
  else if (FD_tolerant & ( go_rx_id1 | go_rx_id2 | go_rx_dlc | go_rx_data | go_rx_crc |
           go_rx_ack | go_rx_eof | go_rx_inter | go_error_frame | go_overload_frame | go_rx_skip_fdf ) )
    bit_cnt <= 9'd0;
  else if (go_rx_id1 | go_rx_id2 | go_rx_dlc | go_rx_data | go_rx_stuff_count | go_rx_crc |
          go_rx_ack | go_rx_eof | go_rx_inter | go_error_frame | go_overload_frame)
    bit_cnt <= 9'd0;
  else if ( sample_point & (~bit_de_stuff) & (~bit_de_stuff_rx_stuff_count) )
    bit_cnt <= bit_cnt + 1'b1;
end


// eof_cnt
always @ (posedge clk or posedge rst)
begin
  if (rst)
    eof_cnt <= 3'd0;
  else if (sample_point)
    begin
      if ( FD_tolerant & (go_rx_inter | go_error_frame | go_overload_frame | go_rx_skip_fdf) )
        eof_cnt <= 3'd0;
      if (go_rx_inter | go_error_frame | go_overload_frame)
        eof_cnt <= 3'd0;
      else if (rx_eof)
        eof_cnt <= eof_cnt + 1'b1;
    end
end


// Enabling bit de-stuffing
always @ (posedge clk or posedge rst)
begin
  if (rst)
    bit_stuff_cnt_en <= 1'b0;
  else if (bit_de_stuff_set)
    bit_stuff_cnt_en <= 1'b1;
  else if (bit_de_stuff_reset)
    bit_stuff_cnt_en <= 1'b0;
end


// bit_stuff_cnt
always @ (posedge clk or posedge rst)
begin
  if (rst)
    bit_stuff_cnt <= 3'h1;
  else if (bit_de_stuff_reset)
    bit_stuff_cnt <= 3'h1;
  else if (sample_point & bit_stuff_cnt_en)
    begin
      if (bit_stuff_cnt == 3'h5)
        bit_stuff_cnt <= 3'h1;
      else if (sampled_bit == sampled_bit_q)
        bit_stuff_cnt <= bit_stuff_cnt + 1'b1;
      else
        bit_stuff_cnt <= 3'h1;
    end
end


// bit_stuff_cnt_tx
always @ (posedge clk or posedge rst)
begin
  if (rst)
    bit_stuff_cnt_tx <= 3'h1;
  else if (reset_mode || bit_de_stuff_reset)
    bit_stuff_cnt_tx <= 3'h1;
  else if (tx_point_q & bit_stuff_cnt_en)
    begin
      if (bit_stuff_cnt_tx == 3'h5)
        bit_stuff_cnt_tx <= 3'h1;
      else if (tx == tx_q)
        bit_stuff_cnt_tx <= bit_stuff_cnt_tx + 1'b1;
      else
        bit_stuff_cnt_tx <= 3'h1;
    end
end


// Bit Stuff detection on RX Must Be Multiplexed
always_comb begin
  if(edl & (rx_crc)) begin
    bit_de_stuff = 1'b0;
  end
  else begin
    bit_de_stuff = (bit_stuff_cnt == 3'h5);
  end
end

assign bit_de_stuff_tx = bit_stuff_cnt_tx == 3'h5;


// STUFF COUNT CHECK - Modulo 8 counter
reg  [3:0] bit_stuff_before_fixed_stuff_bit;
reg  [2:0] bit_stuff_before_fixed_stuff_bit_mod_8;
wire [2:0] bit_stuff_gray_counter;
wire       stuff_cnt_parity_check;        

always @ (posedge clk or posedge rst)
begin
  if (rst)
  begin
    bit_stuff_before_fixed_stuff_bit <= 4'b0;
  end
  else if (sample_point & en_FD_iso & (rx_crc | go_error_frame)) begin
    bit_stuff_before_fixed_stuff_bit <= 4'b0; 
  end
  else if(sample_point & bit_de_stuff & en_FD_iso)
  begin
      bit_stuff_before_fixed_stuff_bit <= bit_stuff_before_fixed_stuff_bit + 4'b0001;
  end
end

assign bit_stuff_before_fixed_stuff_bit_mod_8 = bit_stuff_before_fixed_stuff_bit % 8;
assign bit_stuff_gray_counter = bit_stuff_before_fixed_stuff_bit_mod_8 ^ (bit_stuff_before_fixed_stuff_bit_mod_8 >> 1);
assign stuff_cnt_parity_check = (( stuff_cnt[3] ^ stuff_cnt[2] ^ stuff_cnt[1] ) == stuff_cnt[0]);

// stuff_err
assign stuff_err = (sample_point & bit_stuff_cnt_en & bit_de_stuff & (sampled_bit == sampled_bit_q));


// Generating delayed signals
always @ (posedge clk or posedge rst)
begin
  if (rst)
    begin
      reset_mode_q <= 1'b0;
      node_bus_off_q <= 1'b0;
    end
  else
    begin
      reset_mode_q <= reset_mode;
      node_bus_off_q <= node_bus_off;
    end
end



always @ (posedge clk or posedge rst)
begin
  if (rst)
    crc_enable <= 1'b0;
  else if (rst_crc_enable)
    crc_enable <= 1'b0;
  else if (go_crc_enable)
    crc_enable <= 1'b1;
end


// CRC error generation
always @ (posedge clk or posedge rst)
begin
  if (rst)
    crc_err <= 1'b0;
  else if (FD_tolerant & (reset_mode | error_frame_ended | fd_skip_finished))
    crc_err <= 1'b0;
  else if (reset_mode | error_frame_ended)
    crc_err <= 1'b0;
  else if (go_rx_ack & ~edl)
    crc_err <= crc_in_15 != calculated_crc_15;
  else if (go_rx_ack & edl & data_len <= 7'd16)
    crc_err <= crc_in_17 != calculated_crc_17;
  else if (go_rx_ack & edl & data_len > 7'd16)
    crc_err <= crc_in_21 != calculated_crc_21;
  else if ((rx_crc && bit_cnt == 9'b0) & edl & en_FD_iso )
    crc_err <= ( stuff_cnt[3:1] != bit_stuff_gray_counter ) & stuff_cnt_parity_check;
end


// Conditions for form error
assign form_err = sample_point & ( ((~bit_de_stuff) & rx_crc_lim & (~sampled_bit)                  ) |
                                   (                  rx_ack_lim & (~sampled_bit)                  ) |
                                   ((eof_cnt < 3'd6)& rx_eof     & (~sampled_bit) & (~transmitter) ) |
                                   (                & rx_eof     & (~sampled_bit) &   transmitter  ) |
                                   (fixed_stuff_bit_error)
                                 );


always @ (posedge clk or posedge rst)
begin
  if (rst)
    ack_err_latched <= 1'b0;
  else if (FD_tolerant & (reset_mode | error_frame_ended | go_overload_frame | fd_skip_finished) )
    ack_err_latched <= 1'b0;
  else if (reset_mode | error_frame_ended | go_overload_frame)
    ack_err_latched <= 1'b0;
  else if (ack_err)
    ack_err_latched <= 1'b1;
end


always @ (posedge clk or posedge rst)
begin
  if (rst)
    bit_err_latched <= 1'b0;
  else if (FD_tolerant & (reset_mode | error_frame_ended | go_overload_frame | fd_skip_finished))
    bit_err_latched <= 1'b0;
  else if (reset_mode | error_frame_ended | go_overload_frame)
    bit_err_latched <= 1'b0;
  else if (bit_err)
    bit_err_latched <= 1'b1;
end



// Rule 5 (Fault confinement).
assign rule5 = bit_err &  ( (~node_error_passive) & error_frame    & (error_cnt1    < 3'd7)
                            |
                                                    overload_frame & (overload_cnt1 < 3'd7)
                          );

// Rule 3 exception 1 - first part (Fault confinement).
always @ (posedge clk or posedge rst)
begin
  if (rst)
    rule3_exc1_1 <= 1'b0;
  else if (error_flag_over | rule3_exc1_2)
    rule3_exc1_1 <= 1'b0;
  else if (transmitter & node_error_passive & ack_err)
    rule3_exc1_1 <= 1'b1;
end


// Rule 3 exception 1 - second part (Fault confinement).
always @ (posedge clk or posedge rst)
begin
  if (rst)
    rule3_exc1_2 <= 1'b0;
  else if (go_error_frame | rule3_exc1_2)
    rule3_exc1_2 <= 1'b0;
  else if (rule3_exc1_1 & (error_cnt1 < 3'd7) & sample_point & (~sampled_bit))
    rule3_exc1_2 <= 1'b1;
end


always @ (posedge clk or posedge rst)
begin
  if (rst)
    stuff_err_latched <= 1'b0;
  else if (FD_tolerant &  (reset_mode | error_frame_ended | go_overload_frame | fd_skip_finished) )
    stuff_err_latched <= 1'b0;
  else if (reset_mode | error_frame_ended | go_overload_frame)
    stuff_err_latched <= 1'b0;
  else if (stuff_err)
    stuff_err_latched <= 1'b1;
end



always @ (posedge clk or posedge rst)
begin
  if (rst)
    form_err_latched <= 1'b0;
  else if (FD_tolerant & (reset_mode | error_frame_ended | go_overload_frame | fd_skip_finished))
    form_err_latched <= 1'b0;
  else if (reset_mode | error_frame_ended | go_overload_frame)
    form_err_latched <= 1'b0;
  else if (form_err)
    form_err_latched <= 1'b1;
end



// Instantiation of the RX CRC module
can_crc i_can_crc_rx
(
  .clk(clk),
  .rst(rst),
  .data(sampled_bit),
  .stuff_bit(bit_de_stuff),
  .FD_iso(en_FD_iso),
  .enable(crc_enable & sample_point & (~bit_de_stuff_rx_stuff_count)),
  .initialize(go_crc_enable),
  .crc_15(calculated_crc_15),
  .crc_17(calculated_crc_17),
  .crc_21(calculated_crc_21)
);


// Somente frames CAN clássicos são transmitidos
assign calculated_crc_tx = calculated_crc_15;

assign no_byte0 = rtr1 | (data_len<7'h1);
assign no_byte1 = rtr1 | (data_len<7'h2);

assign go_rx_inter_acf = FD_tolerant ? (go_rx_inter & (~rx_skip_fdf)) : go_rx_inter;
assign go_error_frame_acf = FD_tolerant ? (go_error_frame | go_rx_skip_fdf) : go_error_frame;

can_acf i_can_acf
(
  .clk(clk),
  .rst(rst),

  .id(id),

  /* Mode register */
  .reset_mode(reset_mode),
  .acceptance_filter_mode(acceptance_filter_mode),

  // Clock Divider register
  .extended_mode(extended_mode),

  /* This section is for BASIC and EXTENDED mode */
  /* Acceptance code register */
  .acceptance_code_0(acceptance_code_0),

  /* Acceptance mask register */
  .acceptance_mask_0(acceptance_mask_0),
  /* End: This section is for BASIC and EXTENDED mode */

  /* This section is for EXTENDED mode */
  /* Acceptance code register */
  .acceptance_code_1(acceptance_code_1),
  .acceptance_code_2(acceptance_code_2),
  .acceptance_code_3(acceptance_code_3),

  /* Acceptance mask register */
  .acceptance_mask_1(acceptance_mask_1),
  .acceptance_mask_2(acceptance_mask_2),
  .acceptance_mask_3(acceptance_mask_3),
  /* End: This section is for EXTENDED mode */

  .go_rx_crc_lim(go_rx_crc_lim),

  .go_rx_inter(go_rx_inter_acf),
  .go_error_frame(go_error_frame_acf),

  .data0( tmp_fifo[0][7:0]),
  .data1( extended_mode ? tmp_fifo[1][15:8] : tmp_fifo[1][7:0]),
  .rtr1(rtr1),
  .rtr2(rtr2),
  .ide(ide),
  .no_byte0(no_byte0),
  .no_byte1(no_byte1),

  .id_ok(id_ok)

);




assign header_len[2:0] = extended_mode ? (ide? (3'h5) : (3'h3)) : 3'h2;
assign storing_header = header_cnt < header_len;

assign limited_data_len_minus1[6:0] = remote_rq ? 7'hf : (data_len -1'b1);   // - 1 because counter counts from 0



assign reset_wr_fifo =  ( (~extended_mode & (data_cnt == (limited_data_len_minus1 + {4'b0, header_len}))) 
                          |
                          (
                            extended_mode & ( 
                              ( ~(&data_len[1:0]) & data_cnt  == (data_len >> 2) + header_len - 1'b1 ) // data_len = 4*k bytes
                              | ( (|data_len[1:0]) & data_cnt  == (data_len >> 2) + header_len ) // data_len < 4 bytes or 4 bytes < data_len < 8 bytes
                              )
                          )
                        ) || reset_mode;

assign err = form_err | stuff_err | bit_err | ack_err | form_err_latched | stuff_err_latched | bit_err_latched | ack_err_latched | crc_err;



// Write enable signal for 64-byte rx fifo
// For now, FD frames should not be written on RX Fifo, once its depth isn't enought
always @ (posedge clk or posedge rst)
begin
  if (rst)
    wr_fifo <= 1'b0;
  else if (reset_wr_fifo)
    wr_fifo <= 1'b0;
  else if ( (go_rx_inter & id_ok & (~error_frame_ended) & ((~tx_state) | self_rx_request)) & ~(rx_skip_fdf) )
    wr_fifo <= 1'b1;
end


// Header counter. Header length depends on the mode of operation and frame format.
always @ (posedge clk or posedge rst)
begin
  if (rst)
    header_cnt <= 3'h0;
  else if (reset_wr_fifo)
    header_cnt <= 3'h0;
  else if (wr_fifo & storing_header)
    header_cnt <= header_cnt + 1'h1;
end


// Data counter. Length of the data is limited to 8 bytes.
always @ (posedge clk or posedge rst)
begin
  if (rst)
    data_cnt <= 7'h0;
  else if (reset_wr_fifo)
    data_cnt <= 7'h0;
  else if (wr_fifo)
    data_cnt <= data_cnt + 7'h1;
end

logic [3:0] fifo_data_wr_index;

assign fifo_data_wr_index =  data_cnt - {1'b0, header_len};

// Multiplexing data that is stored to 64-byte fifo depends on the mode of operation and frame format
always_comb
begin
  casex ({storing_header, extended_mode, ide, header_cnt, edl}) /* synthesis parallel_case */
    7'b1_1_1_000_0  : data_for_fifo = { 24'b0, {1'b1, rtr2, 2'h0, data_len_code}};            // extended mode, extended format header 
    7'b1_1_1_000_1  : data_for_fifo = { 23'b0, {1'b1, 1'b1, rtr2, brs, esi, data_len_code}};  // extended mode, extended format header -> FD Frame
    7'b1_1_1_001_x  : data_for_fifo = { 24'b0, id[28:21]};                               // extended mode, extended format header
    7'b1_1_1_010_x  : data_for_fifo = { 24'b0, id[20:13]};                               // extended mode, extended format header
    7'b1_1_1_011_x  : data_for_fifo = { 24'b0, id[12:5]};                                // extended mode, extended format header
    7'b1_1_1_100_x  : data_for_fifo = { 24'b0, {id[4:0], 3'h0}};                         // extended mode, extended format header
    7'b1_1_0_000_0  : data_for_fifo = { 24'b0, {1'b0, rtr1, 2'h0, data_len_code}};       // extended mode, standard format header
    7'b1_1_0_000_1  : data_for_fifo = { 24'b0, {1'b1, 1'b0, rtr1, brs, esi, data_len_code}};  // extended mode, standard format header -> FD Frame
    7'b1_1_0_001_x  : data_for_fifo = { 24'b0, id[10:3]};                                // extended mode, standard format header
    7'b1_1_0_010_x  : data_for_fifo = { 24'b0, {id[2:0], rtr1, 4'h0}};                   // extended mode, standard format header
    7'b1_0_x_000_x  : data_for_fifo = { 24'b0, id[10:3]};                                // normal mode                    header
    7'b1_0_x_001_x  : data_for_fifo = { 24'b0, {id[2:0], rtr1, data_len_code}};          // normal mode                    header
    default         : data_for_fifo = tmp_fifo[fifo_data_wr_index];   // data
  endcase
end



// Instantiation of the RX fifo module
can_fifo i_can_fifo
(
  .clk(clk),
  .rst(rst),

  .wr(wr_fifo),

  .data_in(data_for_fifo),
  .addr(addr[5:0]),
  .data_out(data_out),
  .fifo_selected(fifo_selected),
  .reset_mode(reset_mode),
  .release_buffer(release_buffer),
  .extended_mode(extended_mode),
  .overrun(overrun),
  .info_empty(info_empty),
  .info_cnt(rx_message_counter)
);


always @ (posedge clk or posedge rst)
begin
  if (rst)
    error_cnt1 <= 3'd0;
  else if (error_frame_ended | go_error_frame | go_overload_frame)
    error_cnt1 <= 3'd0;
  else if (error_frame & tx_point & (error_cnt1 < 3'd7))
    error_cnt1 <= error_cnt1 + 1'b1;
end



assign error_flag_over = ((~node_error_passive) & sample_point & (error_cnt1 == 3'd7) | node_error_passive  & sample_point & (passive_cnt == 3'h6)) & (~enable_error_cnt2);


always @ (posedge clk or posedge rst)
begin
  if (rst)
    error_flag_over_latched <= 1'b0;
  else if (error_frame_ended | go_error_frame | go_overload_frame)
    error_flag_over_latched <= 1'b0;
  else if (error_flag_over)
    error_flag_over_latched <= 1'b1;
end


always @ (posedge clk or posedge rst)
begin
  if (rst)
    enable_error_cnt2 <= 1'b0;
  else if (error_frame_ended | go_error_frame | go_overload_frame)
    enable_error_cnt2 <= 1'b0;
  else if (error_frame & (error_flag_over & sampled_bit))
    enable_error_cnt2 <= 1'b1;
end


always @ (posedge clk or posedge rst)
begin
  if (rst)
    error_cnt2 <= 3'd0;
  else if (error_frame_ended | go_error_frame | go_overload_frame)
    error_cnt2 <= 3'd0;
  else if (enable_error_cnt2 & tx_point)
    error_cnt2 <= error_cnt2 + 1'b1;
end


always @ (posedge clk or posedge rst)
begin
  if (rst)
    delayed_dominant_cnt <= 3'h0;
  else if (enable_error_cnt2 | go_error_frame | enable_overload_cnt2 | go_overload_frame)
    delayed_dominant_cnt <= 3'h0;
  else if (sample_point & (~sampled_bit) & ((error_cnt1 == 3'd7) | (overload_cnt1 == 3'd7)))
    delayed_dominant_cnt <= delayed_dominant_cnt + 1'b1;
end


// passive_cnt
always @ (posedge clk or posedge rst)
begin
  if (rst)
    passive_cnt <= 3'h1;
  else if (error_frame_ended | go_error_frame | go_overload_frame | first_compare_bit)
    passive_cnt <= 3'h1;
  else if (sample_point & (passive_cnt < 3'h6))
    begin
      if (error_frame & (~enable_error_cnt2) & (sampled_bit == sampled_bit_q))
        passive_cnt <= passive_cnt + 1'b1;
      else
        passive_cnt <= 3'h1;
    end
end


// When comparing 6 equal bits, first is always equal
always @ (posedge clk or posedge rst)
begin
  if (rst)
    first_compare_bit <= 1'b0;
  else if (go_error_frame)
    first_compare_bit <= 1'b1;
  else if (sample_point)
    first_compare_bit <= 1'b0;
end


always @ (posedge clk or posedge rst)
begin
  if (rst)
    overload_cnt1 <= 3'd0;
  else if (overload_frame_ended | go_error_frame | go_overload_frame)
    overload_cnt1 <= 3'd0;
  else if (overload_frame & tx_point & (overload_cnt1 < 3'd7))
    overload_cnt1 <= overload_cnt1 + 1'b1;
end


assign overload_flag_over = sample_point & (overload_cnt1 == 3'd7) & (~enable_overload_cnt2);


always @ (posedge clk or posedge rst)
begin
  if (rst)
    enable_overload_cnt2 <= 1'b0;
  else if (overload_frame_ended | go_error_frame | go_overload_frame)
    enable_overload_cnt2 <= 1'b0;
  else if (overload_frame & (overload_flag_over & sampled_bit))
    enable_overload_cnt2 <= 1'b1;
end


always @ (posedge clk or posedge rst)
begin
  if (rst)
    overload_cnt2 <= 3'd0;
  else if (overload_frame_ended | go_error_frame | go_overload_frame)
    overload_cnt2 <= 3'd0;
  else if (enable_overload_cnt2 & tx_point)
    overload_cnt2 <= overload_cnt2 + 1'b1;
end


always @ (posedge clk or posedge rst)
begin
  if (rst)
    overload_request_cnt <= 2'b0;
  else if (go_error_frame | go_rx_id1)
    overload_request_cnt <= 2'b0;
  else if (overload_request & overload_frame)
    overload_request_cnt <= overload_request_cnt + 1'b1;
end


always @ (posedge clk or posedge rst)
begin
  if (rst)
    overload_frame_blocked <= 1'b0;
  else if (go_error_frame | go_rx_id1)
    overload_frame_blocked <= 1'b0;
  else if (FD_tolerant & go_rx_skip_fdf)
    overload_frame_blocked <= 1'b1;
  else if (overload_request & overload_frame & overload_request_cnt == 2'h2)   // This is a second sequential overload_request
    overload_frame_blocked <= 1'b1;
end


assign send_ack = (~tx_state) & (rx_ack | rx_ack_fd_1) & (~err) & (~listen_only_mode);



always @ (*)
begin
  if (reset_mode | node_bus_off)                                                // Reset or node_bus_off
    tx_next = 1'b1;
  else
    begin
      if (go_error_frame | error_frame)                                         // Transmitting error frame
        begin
          if (error_cnt1 < 3'd6)
            begin
              if (node_error_passive)
                tx_next = 1'b1;
              else
                tx_next = 1'b0;
            end
          else
            tx_next = 1'b1;
        end
      else if (go_overload_frame | overload_frame)                              // Transmitting overload frame
        begin
          if (overload_cnt1 < 3'd6)
            tx_next = 1'b0;
          else
            tx_next = 1'b1;
        end
      else if (go_tx | tx_state)                                                        // Transmitting message
        tx_next = ((~bit_de_stuff_tx) & tx_bit) | (bit_de_stuff_tx & (~tx_q));
      else if (send_ack)                                                        // Acknowledge
        tx_next = 1'b0;
      else
        tx_next = 1'b1;
    end
end


always @ (posedge clk or posedge rst)
begin
  if (rst)
    tx <= 1'b1;
  else if (reset_mode)
    tx <= 1'b1;
  else if (FD_tolerant & tx_point)
    tx <= (tx_next | rx_skip_fdf);
  else if (tx_point)
    tx <= tx_next;
end


always @ (posedge clk or posedge rst)
begin
  if (rst)
    tx_q <= 1'b0;
  else if (reset_mode)
    tx_q <= 1'b0;
  else if (tx_point)
    tx_q <= tx & (~go_early_tx_latched);
end


/* Delayed tx point */
always @ (posedge clk or posedge rst)
begin
  if (rst)
    tx_point_q <= 1'b0;
  else if (reset_mode)
    tx_point_q <= 1'b0;
  else
    tx_point_q <= tx_point;
end


/* Changing bit order from [7:0] to [0:7] */
can_ibo i_ibo_tx_data_0  (.di_ibo(tx_data_0),  .do_ibo(r_tx_data_0));
can_ibo i_ibo_tx_data_1  (.di_ibo(tx_data_1),  .do_ibo(r_tx_data_1));
can_ibo i_ibo_tx_data_2  (.di_ibo(tx_data_2),  .do_ibo(r_tx_data_2));
can_ibo i_ibo_tx_data_3  (.di_ibo(tx_data_3),  .do_ibo(r_tx_data_3));
can_ibo i_ibo_tx_data_4  (.di_ibo(tx_data_4),  .do_ibo(r_tx_data_4));
can_ibo i_ibo_tx_data_5  (.di_ibo(tx_data_5),  .do_ibo(r_tx_data_5));
can_ibo i_ibo_tx_data_6  (.di_ibo(tx_data_6),  .do_ibo(r_tx_data_6));
can_ibo i_ibo_tx_data_7  (.di_ibo(tx_data_7),  .do_ibo(r_tx_data_7));
can_ibo i_ibo_tx_data_8  (.di_ibo(tx_data_8),  .do_ibo(r_tx_data_8));
can_ibo i_ibo_tx_data_9  (.di_ibo(tx_data_9),  .do_ibo(r_tx_data_9));
can_ibo i_ibo_tx_data_10 (.di_ibo(tx_data_10), .do_ibo(r_tx_data_10));
can_ibo i_ibo_tx_data_11 (.di_ibo(tx_data_11), .do_ibo(r_tx_data_11));
can_ibo i_ibo_tx_data_12 (.di_ibo(tx_data_12), .do_ibo(r_tx_data_12));

/* Changing bit order from [14:0] to [0:14] */
can_ibo i_calculated_crc0 (.di_ibo(calculated_crc_tx[14:7]), .do_ibo(r_calculated_crc[7:0]));
can_ibo i_calculated_crc1 (.di_ibo({calculated_crc_tx[6:0], 1'b0}), .do_ibo(r_calculated_crc[15:8]));


assign basic_chain = {r_tx_data_1[7:4], 2'h0, r_tx_data_1[3:0], r_tx_data_0[7:0], 1'b0};
assign basic_chain_data = {r_tx_data_9, r_tx_data_8, r_tx_data_7, r_tx_data_6, r_tx_data_5, r_tx_data_4, r_tx_data_3, r_tx_data_2};
assign extended_chain_std = {r_tx_data_0[7:4], 2'h0, r_tx_data_0[1], r_tx_data_2[2:0], r_tx_data_1[7:0], 1'b0};
assign extended_chain_ext = {r_tx_data_0[7:4], 2'h0, r_tx_data_0[1], r_tx_data_4[4:0], r_tx_data_3[7:0], r_tx_data_2[7:3], 1'b1, 1'b1, r_tx_data_2[2:0], r_tx_data_1[7:0], 1'b0};
assign extended_chain_data_std = {r_tx_data_10, r_tx_data_9, r_tx_data_8, r_tx_data_7, r_tx_data_6, r_tx_data_5, r_tx_data_4, r_tx_data_3};
assign extended_chain_data_ext = {r_tx_data_12, r_tx_data_11, r_tx_data_10, r_tx_data_9, r_tx_data_8, r_tx_data_7, r_tx_data_6, r_tx_data_5};

always @ (extended_mode or rx_data or tx_pointer or extended_chain_data_std or extended_chain_data_ext or rx_crc or r_calculated_crc or
          r_tx_data_0   or extended_chain_ext or extended_chain_std or basic_chain_data or basic_chain or
          finish_msg)
begin
  if (extended_mode)
    begin
      if (rx_data)  // data stage
        if (r_tx_data_0[0])    // Extended frame
          tx_bit = extended_chain_data_ext[tx_pointer];
        else
          tx_bit = extended_chain_data_std[tx_pointer];
      else if (rx_crc)
        tx_bit = r_calculated_crc[tx_pointer];
      else if (finish_msg)
        tx_bit = 1'b1;
      else
        begin
          if (r_tx_data_0[0])    // Extended frame
            tx_bit = extended_chain_ext[tx_pointer];
          else
            tx_bit = extended_chain_std[tx_pointer];
        end
    end
  else  // Basic mode
    begin
      if (rx_data)  // data stage
        tx_bit = basic_chain_data[tx_pointer];
      else if (rx_crc)
        tx_bit = r_calculated_crc[tx_pointer];
      else if (finish_msg)
        tx_bit = 1'b1;
      else
        tx_bit = basic_chain[tx_pointer];
    end
end


assign limited_tx_cnt_ext = tx_data_0[3] ? 6'h3f : ((tx_data_0[2:0] <<3) - 1'b1);
assign limited_tx_cnt_std = tx_data_1[3] ? 6'h3f : ((tx_data_1[2:0] <<3) - 1'b1);

assign rst_tx_pointer = ((~bit_de_stuff_tx) & tx_point & (~rx_data) &   extended_mode  &   r_tx_data_0[0]   & tx_pointer == 6'd38             ) |   // arbitration + control for extended format
                        ((~bit_de_stuff_tx) & tx_point & (~rx_data) &   extended_mode  & (~r_tx_data_0[0])  & tx_pointer == 6'd18             ) |   // arbitration + control for extended format
                        ((~bit_de_stuff_tx) & tx_point & (~rx_data) & (~extended_mode)                      & tx_pointer == 6'd18             ) |   // arbitration + control for standard format
                        ((~bit_de_stuff_tx) & tx_point &   rx_data  &   extended_mode                       & tx_pointer == limited_tx_cnt_ext) |   // data       (overflow is OK here)
                        ((~bit_de_stuff_tx) & tx_point &   rx_data  & (~extended_mode)                      & tx_pointer == limited_tx_cnt_std) |   // data       (overflow is OK here)
                        (                     tx_point &   rx_crc_lim                                                                         ) |   // crc
                        (go_rx_idle                                                                                                           ) |   // at the end
                        (reset_mode                                                                                                           ) |
                        (overload_frame                                                                                                       ) |
                        (error_frame                                                                                                          ) ;

always @ (posedge clk or posedge rst)
begin
  if (rst)
    tx_pointer <= 6'h0;
  else if (rst_tx_pointer)
    tx_pointer <= 6'h0;
  else if (go_early_tx | (tx_point & (tx_state | go_tx) & (~bit_de_stuff_tx)))
    tx_pointer <= tx_pointer + 1'b1;
end



assign tx_successful = FD_tolerant ? (transmitter & go_rx_inter & (~go_error_frame) & (~error_frame_ended) & (~overload_frame_ended) & (~arbitration_lost) & (~rx_skip_fdf)) :
 (transmitter & go_rx_inter & (~go_error_frame) & (~error_frame_ended) & (~overload_frame_ended) & (~arbitration_lost));



always @ (posedge clk or posedge rst)
begin
  if (rst)
    need_to_tx <= 1'b0;
  else if (tx_successful | reset_mode | (abort_tx & (~transmitting)) | ((~tx_state) & tx_state_q & single_shot_transmission))
    need_to_tx <= 1'h0;
  else if (tx_request & sample_point)
    need_to_tx <= 1'b1;
end



assign go_early_tx = (~listen_only_mode) & need_to_tx & (~tx_state) & (~suspend | (susp_cnt == 3'h7)) & sample_point & (~sampled_bit) & (rx_idle | last_bit_of_inter);
assign go_tx       = (~listen_only_mode) & need_to_tx & (~tx_state) & (~suspend | (sample_point & (susp_cnt == 3'h7))) & (go_early_tx | rx_idle);

// go_early_tx latched (for proper bit_de_stuff generation)
always @ (posedge clk or posedge rst)
begin
  if (rst)
    go_early_tx_latched <= 1'b0;
  else if (reset_mode || tx_point)
    go_early_tx_latched <= 1'b0;
  else if (go_early_tx)
    go_early_tx_latched <= 1'b1;
end



// Tx state
always @ (posedge clk or posedge rst)
begin
  if (rst)
    tx_state <= 1'b0;
  else if (FD_tolerant &  (reset_mode | go_rx_inter | error_frame | arbitration_lost | go_rx_skip_fdf | rx_skip_fdf) )
    tx_state <= 1'b0;
  else if (reset_mode | go_rx_inter | error_frame | arbitration_lost)
    tx_state <= 1'b0;
  else if (go_tx)
    tx_state <= 1'b1;
end

always @ (posedge clk or posedge rst)
begin
  if (rst)
    tx_state_q <= 1'b0;
  else if (reset_mode)
    tx_state_q <= 1'b0;
  else
    tx_state_q <= tx_state;
end



// Node is a transmitter
always @ (posedge clk or posedge rst)
begin
  if (rst)
    transmitter <= 1'b0;
  else if (go_tx)
    transmitter <= 1'b1;
  else if (reset_mode | go_rx_idle | suspend & go_rx_id1)
    transmitter <= 1'b0;
end


always @ (posedge clk or posedge rst)
begin
  if (rst)
    suspend <= 1'b0;
  else if (reset_mode | (sample_point & (susp_cnt == 3'h7)))
    suspend <= 1'b0;
  /* This looks like trouble when the TX frame is queued just after leaving INTER - we won't wait at all! */
  else if (not_first_bit_of_inter & transmitter & node_error_passive)
    suspend <= 1'b1;
end


always @ (posedge clk or posedge rst)
begin
  if (rst)
    susp_cnt_en <= 1'b0;
  else if (reset_mode | (sample_point & (susp_cnt == 3'h7)))
    susp_cnt_en <= 1'b0;
  else if (FD_tolerant & (suspend & sample_point & (last_bit_of_inter | fd_skip_finished)))
    susp_cnt_en <= 1'b1;
  else if (suspend & sample_point & last_bit_of_inter)
    susp_cnt_en <= 1'b1;
end


always @ (posedge clk or posedge rst)
begin
  if (rst)
    susp_cnt <= 3'h0;
  else if (reset_mode | (sample_point & (susp_cnt == 3'h7)))
    susp_cnt <= 3'h0;
  else if (susp_cnt_en & sample_point)
    susp_cnt <= susp_cnt + 1'b1;
end


always @ (posedge clk or posedge rst)
begin
  if (rst)
    finish_msg <= 1'b0;
  else if (FD_tolerant & (go_rx_idle | go_rx_id1 | error_frame | reset_mode | rx_skip_fdf))
    finish_msg <= 1'b0;
  else if (go_rx_idle | go_rx_id1 | error_frame | reset_mode)
    finish_msg <= 1'b0;
  else if (go_rx_crc_lim)
    finish_msg <= 1'b1;
end


always @ (posedge clk or posedge rst)
begin
  if (rst)
    arbitration_lost <= 1'b0;
  else if (FD_tolerant & (go_rx_idle | error_frame_ended | fd_skip_finished)) // fd_skip_finished may be unnecessary
    arbitration_lost <= 1'b0;
  else if (go_rx_idle | error_frame_ended)
    arbitration_lost <= 1'b0;
    // in FD tolerant mode, when FDF=1 during TX, it means bit error, not arbitration loss
  else if (transmitter & sample_point & tx & arbitration_field & ~sampled_bit)
    arbitration_lost <= 1'b1;
end


always @ (posedge clk or posedge rst)
begin
  if (rst)
    arbitration_lost_q <= 1'b0;
  else
    arbitration_lost_q <= arbitration_lost;
end


always @ (posedge clk or posedge rst)
begin
  if (rst)
    arbitration_field_d <= 1'b0;
  else if (sample_point)
    arbitration_field_d <= arbitration_field;
end


assign set_arbitration_lost_irq = arbitration_lost & (~arbitration_lost_q) & (~arbitration_blocked);


always @ (posedge clk or posedge rst)
begin
  if (rst)
    arbitration_cnt <= 5'h0;
  else if (sample_point && !bit_de_stuff)
    if (arbitration_field_d)
      arbitration_cnt <= arbitration_cnt + 1'b1;
    else
      arbitration_cnt <= 5'h0;
end


always @ (posedge clk or posedge rst)
begin
  if (rst)
    arbitration_lost_capture <= 5'h0;
  else if (set_arbitration_lost_irq)
    arbitration_lost_capture <= arbitration_cnt;
end


always @ (posedge clk or posedge rst)
begin
  if (rst)
    arbitration_blocked <= 1'b0;
  else if (read_arbitration_lost_capture_reg)
    arbitration_blocked <= 1'b0;
  else if (set_arbitration_lost_irq)
    arbitration_blocked <= 1'b1;
end


always @ (posedge clk or posedge rst)
begin
  if (rst)
    rx_err_cnt <= 9'h0;
  else if (we_rx_err_cnt & (~node_bus_off))
    rx_err_cnt <= {1'b0, data_in[7:0]};
  else if (set_reset_mode)
    rx_err_cnt <= 9'h0;
  else
    begin
      if ( (FD_tolerant & ((~listen_only_mode) & (~transmitter | arbitration_lost) & (~rx_skip_fdf))) | ((~FD_tolerant) & ((~listen_only_mode) & (~transmitter | arbitration_lost))) )
        begin
          if (go_rx_ack_lim & (~go_error_frame) & (~crc_err) & (rx_err_cnt > 9'h0))
            begin
              if (rx_err_cnt > 9'd127)
                rx_err_cnt <= 9'd127;
              else
                rx_err_cnt <= rx_err_cnt - 1'b1;
            end
          else if (rx_err_cnt < 9'd128)
            begin
              if (go_error_frame & (~rule5))                                                                                          // 1  (rule 5 is just the opposite then rule 1 exception
                rx_err_cnt <= rx_err_cnt + 1'b1;
              else if ( (error_flag_over & (~error_flag_over_latched) & sample_point & (~sampled_bit) & (error_cnt1 == 3'd7)     ) |  // 2
                        (go_error_frame & rule5                                                                                  ) |  // 5
                        (sample_point & (~sampled_bit) & (delayed_dominant_cnt == 3'h7)                            )                  // 6
                      )
                rx_err_cnt <= rx_err_cnt + 4'h8;
            end
        end
    end
end


always @ (posedge clk or posedge rst)
begin
  if (rst)
    tx_err_cnt <= 9'h0;
  else if (we_tx_err_cnt)
    tx_err_cnt <= {1'b0, data_in[7:0]};
  else
    begin
      if (set_reset_mode)
        tx_err_cnt <= 9'd128;
      else if ((tx_err_cnt > 9'd0) & (tx_successful | bus_free))
        tx_err_cnt <= tx_err_cnt - 1'h1;
      else if (transmitter & (~arbitration_lost))
        begin
          if ( (sample_point & (~sampled_bit) & (delayed_dominant_cnt == 3'h7)                                          ) |       // 6
               (go_error_frame & rule5                                                                                  ) |       // 4  (rule 5 is the same as rule 4)
               (go_error_frame & (~(transmitter & node_error_passive & ack_err)) & (~(transmitter & stuff_err &
                arbitration_field & sample_point & tx & (~sampled_bit)))                                                ) |       // 3
               (error_frame & rule3_exc1_2                                                                              )         // 3
             )
            tx_err_cnt <= tx_err_cnt + 4'h8;
        end
    end
end


always @ (posedge clk or posedge rst)
begin
  if (rst)
    node_error_passive <= 1'b0;
  else if ((rx_err_cnt < 128) & (tx_err_cnt < 9'd128))
    node_error_passive <= 1'b0;
  else if (((rx_err_cnt >= 128) | (tx_err_cnt >= 9'd128)) & (error_frame_ended | go_error_frame | (~reset_mode) & reset_mode_q) & (~node_bus_off))
    node_error_passive <= 1'b1;
end


assign node_error_active = ~(node_error_passive | node_bus_off);


always @ (posedge clk or posedge rst)
begin
  if (rst)
    node_bus_off <= 1'b0;
  else if ((rx_err_cnt == 9'h0) & (tx_err_cnt == 9'd0) & (~reset_mode) | (we_tx_err_cnt & (data_in[7:0] < 8'd255)))
    node_bus_off <= 1'b0;
  else if ((tx_err_cnt >= 9'd256) | (we_tx_err_cnt & (data_in[7:0] == 8'd255)))
    node_bus_off <= 1'b1;
end



always @ (posedge clk or posedge rst)
begin
  if (rst)
    bus_free_cnt <= 4'h0;
  else if (sample_point)
    begin
      // TODO: & ~(fdr_r & fd_fall_edge_lstbtm) ?
      if ( FD_tolerant & (sampled_bit & bus_free_cnt_en & (bus_free_cnt < 4'd10) & (~fd_fall_edge_lstbtm)))
        bus_free_cnt <= bus_free_cnt + 1'b1;
      else if (sampled_bit & bus_free_cnt_en & (bus_free_cnt < 4'd10))
        bus_free_cnt <= bus_free_cnt + 1'b1;
      else
        bus_free_cnt <= 4'h0;
    end
end


assign bus_free_uncond = sample_point & sampled_bit & (bus_free_cnt==4'd10);

/* must be delayed to be valid for next sample_point, but not this one */
always @ (posedge clk or posedge rst)
begin
  if (rst)
    bus_free <= 1'b0;
  else
    bus_free <= bus_free_uncond & waiting_for_bus_free;
end

// TODO: merge bus_free_cnt_en and waiting_for_bus_free?

always @ (posedge clk or posedge rst)
begin
  if (rst)
    bus_free_cnt_en <= 1'b0;
  else if ((~reset_mode) & reset_mode_q)
    bus_free_cnt_en <= 1'b1;
  else if (bus_free_uncond & (~node_bus_off))
    bus_free_cnt_en <= 1'b0;
end

always @ (posedge clk or posedge rst)
begin
  if (rst)
    waiting_for_bus_free <= 1'b1;
  else if (reset_mode_q & ~reset_mode)
    waiting_for_bus_free <= 1'b1;
  else if (bus_free_uncond & (~node_bus_off))
    waiting_for_bus_free <= 1'b0;
end


assign bus_off_on = ~node_bus_off;

assign set_reset_mode = node_bus_off & (~node_bus_off_q);
assign error_status = extended_mode? ((rx_err_cnt >= error_warning_limit) | (tx_err_cnt >= error_warning_limit))    :
                                     ((rx_err_cnt >= 9'd96) | (tx_err_cnt >= 9'd96))                                ;

/*
Extended mode:
If both the receive status and the transmit status bits are logic 0 (idle) the CAN-bus is idle. If both bits are set the
controller is waiting to become idle again. After a hardware reset 11 consecutive recessive bits have to be detected
until the idle status is reached. After bus-off this will take 128 of 11 consecutive recessive bits.
(SJA1000, 6.4., SR, Note 3)
*/
assign transmit_status = transmitting  || (extended_mode && waiting_for_bus_free);
assign receive_status  = extended_mode ? (waiting_for_bus_free || (!rx_idle) && (!transmitting)) :
                                         ((!waiting_for_bus_free) && (!rx_idle) && (!transmitting));

/* Error code capture register */
always @ (posedge clk or posedge rst)
begin
  if (rst)
    error_capture_code <= 8'h0;
  else if (read_error_code_capture_reg)
    error_capture_code <= 8'h0;
  else if (set_bus_error_irq)
    error_capture_code <= {error_capture_code_type[7:6], error_capture_code_direction, error_capture_code_segment[4:0]};
end



assign error_capture_code_segment[0] = rx_idle | rx_ide | (rx_id2 & (bit_cnt<9'd13)) | rx_r1 | rx_r0 | rx_dlc | rx_ack | rx_ack_lim | error_frame & node_error_active;
assign error_capture_code_segment[1] = rx_idle | rx_id1 | rx_id2 | rx_dlc | rx_data | rx_ack_lim | rx_eof | rx_inter | error_frame & node_error_passive;
assign error_capture_code_segment[2] = (rx_id1 & (bit_cnt>9'd7)) | rx_rtr1 | rx_ide | rx_id2 | rx_rtr2 | rx_r1 | error_frame & node_error_passive | overload_frame;
assign error_capture_code_segment[3] = (rx_id2 & (bit_cnt>9'd4)) | rx_rtr2 | rx_r1 | rx_r0 | rx_dlc | rx_data | rx_crc | rx_crc_lim | rx_ack | rx_ack_lim | rx_eof | overload_frame;
assign error_capture_code_segment[4] = rx_crc_lim | rx_ack | rx_ack_lim | rx_eof | rx_inter | error_frame | overload_frame;
assign error_capture_code_direction  = ~transmitting;


always @ (bit_err or form_err or stuff_err)
begin
  if (bit_err)
    error_capture_code_type[7:6] = 2'b00;
  else if (form_err)
    error_capture_code_type[7:6] = 2'b01;
  else if (stuff_err)
    error_capture_code_type[7:6] = 2'b10;
  else
    error_capture_code_type[7:6] = 2'b11;
end


assign set_bus_error_irq = go_error_frame & (~error_capture_code_blocked);


always @ (posedge clk or posedge rst)
begin
  if (rst)
    error_capture_code_blocked <= 1'b0;
  else if (read_error_code_capture_reg)
    error_capture_code_blocked <= 1'b0;
  else if (set_bus_error_irq)
    error_capture_code_blocked <= 1'b1;
end


// ########################################################
// # Operation Control FSM
// ######################################################## 
assign go_oc_transmitting = go_error_frame | go_overload_frame | go_tx;
assign go_oc_receiving    = (go_rx_id1 & (~tx_state)) | (arbitration_lost & tx_state);
assign go_oc_idle         = go_rx_idle ;
assign go_oc_integrating  = go_rx_integrating;


can_operation_control_fsm i_can_operation_control_fsm (

    .clk_i(clk),
    .rst_i(rst),

    // Data Path Flags
    .go_oc_integrating_i(go_oc_integrating),
    .go_oc_transmitting_i(go_oc_transmitting),
    .go_oc_receiving_i(go_oc_receiving),
    .go_oc_idle_i(go_oc_idle),
    .reset_mode_i(reset_mode),
    .bus_free_i(bus_free),

    // Current State
    .is_transmitting_o(transmitting)
);


// ########################################################
// # Next State Flags
// ######################################################## 

assign go_rx_integrating = (~reset_mode) & reset_mode_q;
assign go_rx_idle     =                   sample_point &  sampled_bit & last_bit_of_inter | bus_free & (~node_bus_off);
assign go_rx_id1      =                   sample_point &  (~sampled_bit) & (rx_idle | last_bit_of_inter);
assign go_rx_rtr1     = (~bit_de_stuff) & sample_point &  rx_id1  & (bit_cnt[3:0] == 4'd10);
assign go_rx_ide      = (~bit_de_stuff) & sample_point &  rx_rtr1;
assign go_rx_id2      = (~bit_de_stuff) & sample_point &  rx_ide  &   sampled_bit;
assign go_rx_rtr2     = (~bit_de_stuff) & sample_point &  rx_id2  & (bit_cnt[4:0] == 5'd17);
assign go_rx_r1       = (~bit_de_stuff) & sample_point &  rx_rtr2;
assign go_rx_r0       = (~bit_de_stuff) & sample_point & (~sampled_bit) & ( rx_ide | rx_r1 );
assign go_rx_dlc = ( ((~bit_de_stuff) & sample_point &  rx_r0 & (~sampled_bit)  ) |  ((~bit_de_stuff) & sample_point &  rx_esi & ~FD_tolerant ) );
assign go_rx_data     = (~bit_de_stuff) & sample_point &  rx_dlc  & (bit_cnt[1:0] == 2'd3) & (~remote_rq);

// Condicao para entrar no estado de Stuff Count:
// Receber Frame FD E estar no estado DATA E operar como FD ISO E o valor de Bit Count ser igual ao valor do campo DLC
// OU
// Receber Frame FD E estar no estado DLC E operar como FD ISO E o valor do campo DLC ser Zero

assign go_rx_stuff_count = (~bit_de_stuff) & sample_point & (fdf_brs_r) & (en_FD_iso) & (
  (rx_data & (bit_cnt[8:0] == ((data_len<<3) - 1'b1))) 
  | ( (rx_dlc & (bit_cnt[1:0] == 2'd3)) & (~sampled_bit) & (~(|data_len[2:0])) )
);

// Condicao para entrar no estado de CRC:
// Estar no estado DLC E o valor do campo DLC ser Zero OU ser uma remote request (E não operar como FD ISO)
// OU
// Estar no estado DATA E o valor de Bit Count for igual ao valor do campo DLC (E não operar como FD ISO)
// OU
// Estar no último bit do estado Stuff Count
assign go_rx_crc = (~bit_de_stuff) & sample_point & (
                    (~en_FD_iso |  ~fdf_brs_r )  & 
                    ( 
                      (rx_dlc & (bit_cnt[1:0] == 2'd3)) & ((~sampled_bit) & (~(|data_len[2:0])) | remote_rq) | (rx_data & (bit_cnt[8:0] == ((data_len<<3) - 1'b1))) 
                    )
                    | (rx_stuff_count & bit_cnt[1:0] == 2'd3 )
                   );  // overflow works ok at max value (8<<3 = 64 = 0). 0-1 = 6'h3f
assign go_rx_crc_lim  = (~bit_de_stuff) & sample_point &  rx_crc  &  ( ( ~fdf_brs_r & (bit_cnt[3:0] == 4'd14) ) | 
                                                                       (  fdf_brs_r & data_len <= 7'd16 & (bit_cnt[4:0] == 5'd21) ) |
                                                                       (  fdf_brs_r & data_len  > 7'd16 & (bit_cnt[4:0] == 5'd26) )  
                                                                     );
assign go_rx_ack      =  (~bit_de_stuff) & sample_point &  rx_crc_lim & (~edl);
assign go_rx_ack_fd_1 =  (~bit_de_stuff) & sample_point &  rx_crc_lim & (edl) & (en_FD_rx);
assign go_rx_ack_fd_2 =  (~bit_de_stuff) & sample_point &  rx_ack_fd_1;
assign go_rx_ack_lim  =  sample_point &  (rx_ack | rx_ack_fd_2);
assign go_rx_eof      =                   sample_point &  rx_ack_lim;
assign go_rx_inter = FD_tolerant ? ( ((sample_point &  rx_eof  & (eof_cnt == 3'd6)) | error_frame_ended | overload_frame_ended | fd_skip_finished) & (~overload_request) ) : ( ((sample_point &  rx_eof  & (eof_cnt == 3'd6)) | error_frame_ended | overload_frame_ended) & (~overload_request) );
assign go_error_frame = (form_err | stuff_err | bit_err | ack_err | (crc_err & go_rx_eof));
assign error_frame_ended = (error_cnt2 == 3'd7) & tx_point;
assign overload_frame_ended = (overload_cnt2 == 3'd7) & tx_point;
assign go_overload_frame = (     sample_point & ((~sampled_bit) | overload_request) & (rx_eof & (~transmitter) & (eof_cnt == 3'd6) | error_frame_ended | overload_frame_ended) |
                                 sample_point & (~sampled_bit) & rx_inter & (bit_cnt[1:0] < 2'd2) | sample_point & (~sampled_bit) & ((error_cnt2 == 3'd7) | (overload_cnt2 == 3'd7))
                           )
                           & 
                           (~overload_frame_blocked)
                           ;
assign go_crc_enable = FD_tolerant ? ((hard_sync & (~rx_skip_fdf)) | go_tx) : ((hard_sync & ~rx_r0_fd) | go_tx);

// CAN FD r0 State
assign go_rx_r0_fd = (~FD_tolerant) & fdf_detected;

// Sikp FD Detection
assign go_rx_skip_fdf = (FD_tolerant) & fdf_detected;

// CAN FD Bit Rate Switch ( BRS ) State
assign go_rx_brs = sample_point & (~bit_de_stuff) & rx_r0_fd;


// CAN FD ESI State
assign go_rx_esi = rx_brs & sample_point & (~bit_de_stuff);


// ########################################################
// # Protocol Control Final State Machine
// ######################################################## 

can_protocol_control_fsm i_can_protocol_control_fsm (   
    .clk_i(clk),
    .rst_i(rst),

    .go_rx_integrating_i(go_rx_integrating),
    .reset_mode_i(reset_mode),
    .bus_free_i(bus_free),

    .go_rx_inter_i(go_rx_inter),
    .go_rx_idle_i(go_rx_idle),
    .go_overload_frame_i(go_overload_frame),
    .go_error_frame_i(go_error_frame),
    .overload_frame_ended_i(overload_frame_ended),
    .go_rx_skip_fdf_i(go_rx_skip_fdf),
    .go_rx_id1_i(go_rx_id1),
    .go_rx_rtr1_i(go_rx_rtr1),
    .go_rx_rtr2_i(go_rx_rtr2),
    .go_rx_ide_i(go_rx_ide),
    .go_rx_id2_i(go_rx_id2),
    .go_rx_r0_i(go_rx_r0),
    .go_rx_r1_i(go_rx_r1),
    .go_rx_r0_fd_i(go_rx_r0_fd),
    .go_rx_dlc_i(go_rx_dlc),
    .go_rx_crc_i(go_rx_crc),
    .go_rx_crc_lim_i(go_rx_crc_lim),
    .go_rx_ack_i(go_rx_ack),
    .go_rx_ack_lim_i(go_rx_ack_lim),
    .go_rx_data_i(go_rx_data),
    .go_rx_stuff_count_i(go_rx_stuff_count),
    .go_rx_esi_i(go_rx_esi),
    .go_rx_brs_i(go_rx_brs),
    .go_rx_ack_fd_1_i(go_rx_ack_fd_1),
    .go_rx_ack_fd_2_i(go_rx_ack_fd_2),
    .go_rx_eof_i(go_rx_eof),

    .is_inter_o(rx_inter),
    .is_idle_o(rx_idle),
    .is_overload_frame_o(overload_frame),
    .is_error_frame_o(error_frame),
    .is_skip_fdf_o(rx_skip_fdf),
    .is_id1_o(rx_id1),
    .is_rtr1_o(rx_rtr1),
    .is_rtr2_o(rx_rtr2),
    .is_ide_o(rx_ide),
    .is_id2_o(rx_id2),
    .is_r0_o(rx_r0),
    .is_r1_o(rx_r1),
    .is_r0_fd_o(rx_r0_fd),
    .is_dlc_o(rx_dlc),
    .is_crc_o(rx_crc),
    .is_crc_lim_o(rx_crc_lim),
    .is_ack_o(rx_ack),
    .is_ack_lim_o(rx_ack_lim),
    .is_data_o(rx_data),
    .is_stuff_count_o(rx_stuff_count),
    .is_esi_o(rx_esi),
    .is_brs_o(rx_brs),
    .is_ack_fd_1_o(rx_ack_fd_1),
    .is_ack_fd_2_o(rx_ack_fd_2),
    .is_eof_o(rx_eof)

);






endmodule
